package com.shiwaixiangcun.monitor.service.impl;

import com.rabbit.spring.data.search.SearchOperator;
import com.rabbit.spring.data.search.Searchable;
import com.rabbit.spring.data.search.filter.SearchFilter;
import com.rabbit.spring.data.search.filter.SearchFilterHelper;
import com.shiwaixiangcun.baidu.SpeechSynthesisService;
import com.shiwaixiangcun.core.domain.Dictionary;
import com.shiwaixiangcun.core.domain.UploadFileInfo;
import com.shiwaixiangcun.core.exceptions.MonkeyException;
import com.shiwaixiangcun.core.plugin.dto.MonkeyDto;
import com.shiwaixiangcun.core.plugin.upload.FileService;
import com.shiwaixiangcun.core.repository.dictionary.DictionaryRepository;
import com.shiwaixiangcun.core.service.BaseServiceImpl;
import com.shiwaixiangcun.core.utils.MonkeyUtils;
import com.shiwaixiangcun.monitor.domain.*;
import com.shiwaixiangcun.monitor.dto.*;
import com.shiwaixiangcun.monitor.enums.*;
import com.shiwaixiangcun.monitor.repository.*;
import com.shiwaixiangcun.monitor.security.SecurityUtils;
import com.shiwaixiangcun.monitor.service.EarlyWarningService;
import com.shiwaixiangcun.monitor.service.WorkOrderService;
import com.shiwaixiangcun.monitor.service.WorkOrderServiceRecordService;
import com.shiwaixiangcun.monitor.utils.NumberGenerator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by Administrator on 2017-11-22.
 */
@Service
@Transactional
public class EarlyWarningServiceImpl extends BaseServiceImpl<EarlyWarning, Long> implements EarlyWarningService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private EarlyWarningRepository earlyWarningRepository;
    @Autowired
    private NumberGenerator numberGenerator;
    @Autowired
    private WarningContentRepository warningContentRepository;

    @Autowired
    private WorkOrderService workOrderService;
    @Autowired
    private WorkOrderCategoryRepository workOrderCategoryRepository;
    @Autowired
    private WorkOrderServiceRecordRepository workOrderServiceRecordRepository;
    @Autowired
    private DeviceRepository deviceRepository;

    @Autowired
    private SpeechSynthesisService speechSynthesisService;
    @Autowired
    private FileService fileService;
    @Autowired
    private WorkOrderServiceRecordService workOrderServiceRecordService;
    @Autowired
    private SystemSetupRepository systemSetupRepository;
    @Autowired
    private DictionaryRepository dictionaryRepository;

    @Override
    public String findCurrentMaxNumber(Long orgId) {
        return earlyWarningRepository.findNumberByCompanyId(orgId);
    }

    @Override
    public void addEarlyWarning(MonkeyDto monkeyDto) {
        String status = monkeyDto.getString("status");
        EarlyWarning earlyWarning = initEarlyWarning(monkeyDto);
        earlyWarningRepository.save(earlyWarning);
        if (HealthStatus.DANGER.equals(HealthStatus.valueOf(status))) {
            List<WarningContent> warningContentList = warningContentRepository.findByEarlyWarning(earlyWarning.getId());
            if (MonkeyUtils.isNotEmpty(warningContentList)) {
                String waringType = monkeyDto.getString("waringType");
                int falg = 0;
                for (WarningContent warningContent : warningContentList) {
                    if (warningContent.getWarningType().equals(WarningType.valueOf(waringType))) {
                        falg = 1;
                        warningContent.setWarningType(WarningType.valueOf(monkeyDto.getString("waringType")));
                        warningContent.setContent(monkeyDto.getString("content"));
                        warningContent.setWaringTime(new Date());
                        Long orgId = monkeyDto.getLong("orgId");
                        warningContent.setCompanyId(orgId);
                        warningContentRepository.save(warningContent);
                    }
                }
                if (falg == 0) {
                    saveWarningContent(earlyWarning, monkeyDto);
                }
            } else {
                saveWarningContent(earlyWarning, monkeyDto);
            }
        }
    }

    @Override
    public void handleWaring(MonkeyDto monkeyDto) {
        User currentUser = SecurityUtils.getCurrentUser();
        Long waringId = monkeyDto.getLong("waringId");
        EarlyWarning earlyWarning = earlyWarningRepository.findOne(waringId);
        if (MonkeyUtils.isEmpty(earlyWarning)) {
            throw new MonkeyException("无效预警id");
        }
        String serviceType = monkeyDto.getString("serviceType");
        if (MonkeyUtils.isNotEmpty(serviceType)) {
            if (WarningServiceType.Workorder.equals(WarningServiceType.valueOf(serviceType))) {
                WorkOrder workOrder = new WorkOrder();
                String number = numberGenerator.generateWorkOrderNumber();
                workOrder.setNumber(number);
                workOrder.setStatus(WorkOrderStatus.Accepted);
                List<WarningContent> warningContentList = earlyWarning.getWarningContents();
                String waringStr = "";
                for (WarningContent warningContent : warningContentList) {
                    waringStr = warningContent.getWarningType().getLabel();
                }
                String phone = earlyWarning.getPhone();
                if (MonkeyUtils.isEmpty(phone)) {
                    phone = "";
                }
                if (warningContentList.size() > 1) {
                    workOrder.setTitle(earlyWarning.getName() + phone + " 多种数据预警");
                } else {
                    workOrder.setTitle(earlyWarning.getName() + phone + " " + waringStr);
                }
                String otherSituation = monkeyDto.getString("otherSituation");
                workOrder.setContent(otherSituation);
                workOrder.setTimeout(false);
                Long staffId = monkeyDto.getLong("staffId");
                User user = userRepository.findOne(staffId);
                workOrder.setUser(user);
                workOrder.setPriorityLevel(PriorityLevel.valueOf(monkeyDto.getString("priorityLevel")));
                WorkOrderCategory Category = workOrderCategoryRepository.findOne(monkeyDto.getLong("categoryId"));
                workOrder.setCategory(Category);
                workOrderService.save(workOrder);
                String content = SecurityUtils.getCurrentUser().getName() + "分配给" + workOrder.getUser().getName();
                workOrderServiceRecordService.createServiceRecord(workOrder, WorkOrderServiceType.Accepted, content);
                earlyWarning.setWorkOrder(workOrder);
                earlyWarning.setDealResult(currentUser.getName() + "把该预警生成编号为" + workOrder.getNumber() + "的服务工单并分配给" + user.getName() + "处理");
            }
            earlyWarning.setServiceType(WarningServiceType.valueOf(serviceType));
            String result = monkeyDto.getString("result");
            if (WarningServiceType.Equipment_False.equals(WarningServiceType.valueOf(serviceType))) {
                earlyWarning.setDealResult(currentUser.getName() + "已将该预警标记为设备误报，不需要处理");
            }
            if (WarningServiceType.Offline_Processing.equals(WarningServiceType.valueOf(serviceType))) {
                earlyWarning.setDealResult(currentUser.getName() + "已将该预警标记为情况紧急,已线下处理，处理情况:" + result);
            }
            earlyWarningRepository.save(earlyWarning);
        }


    }

    @Override
    public Page<WaringListDto> getWaringHistoryList(Pageable pageable, WaringSearchDto waringSearchDto) {
        Searchable searchable = Searchable.newSearchable();
        searchable.addSort(Sort.Direction.DESC, "createTime");
        searchable.addSearchFilter("status", SearchOperator.eq, HealthStatus.DANGER);
        searchable.addSearchFilter("serviceType", SearchOperator.ne, WarningServiceType.None);
        int pageIndex = pageable.getPageNumber() * pageable.getPageSize();
        int pageSize = pageable.getPageSize();
        if (MonkeyUtils.isNotEmpty(waringSearchDto)) {
            String search = waringSearchDto.getSearch();
            if (MonkeyUtils.isNotEmpty(search)) {
                SearchFilter f1 = SearchFilterHelper.newCondition("number", SearchOperator.like, "%" + search + "%");
                SearchFilter f2 = SearchFilterHelper.newCondition("name", SearchOperator.like, "%" + search + "%");
                searchable.or(f1, f2);
            }
        }
        List<EarlyWarning> warningList = earlyWarningRepository.findAll(searchable).getContent();
        int total = warningList.size();
        List<EarlyWarning> earlyWarningList = limitList(pageIndex, pageSize, total, warningList);
        List<WaringListDto> waringListDtos = initWaringListDto(earlyWarningList);
        return new PageImpl<>(waringListDtos, pageable, total);
    }

    @Override
    public List<DangerWarningListDto> getDangerWarningList() {
        Searchable searchable = Searchable.newSearchable();
        searchable.addSort(Sort.Direction.DESC, "createTime");
        searchable.addSearchFilter("status", SearchOperator.eq, HealthStatus.DANGER);
        searchable.addSearchFilter("serviceType", SearchOperator.eq, WarningServiceType.None);
        List<EarlyWarning> warningList = earlyWarningRepository.findAll(searchable).getContent();
        return buildDangerWarningListDto(warningList);
    }

    @Override
    public WarningDetailDto getWarningDetail(Long waringId) {
        WarningDetailDto warningDetailDto = new WarningDetailDto();
        EarlyWarning earlyWarning = earlyWarningRepository.findOne(waringId);
        if (MonkeyUtils.isEmpty(earlyWarning)) {
            throw new MonkeyException("无效预警ID");
        }
        warningDetailDto.setWaringId(waringId);
        warningDetailDto.setName(earlyWarning.getName());
        warningDetailDto.setAge(earlyWarning.getAge());
        warningDetailDto.setAvatar(earlyWarning.getAvatar());
        warningDetailDto.setPhone(earlyWarning.getPhone());
        Sex sex = earlyWarning.getSex();
        if (MonkeyUtils.isNotEmpty(sex)) {
            warningDetailDto.setSex(sex.getLabel());
        }
        warningDetailDto.setBeeper(earlyWarning.getBeeper());
        warningDetailDto.setServiceType(earlyWarning.getServiceType());
        warningDetailDto.setDealResult(earlyWarning.getDealResult());
        if (WarningServiceType.None.equals(earlyWarning.getServiceType())) {
        } else {
            warningDetailDto.setDealTime(earlyWarning.getLastModifiedDate());
        }
        List<WarningContentDto> warningContentDtoList = new ArrayList<>();
        List<WarningContent> warningContentList = earlyWarning.getWarningContents();
        for (WarningContent warningContent : warningContentList) {
            WarningContentDto warningContentDto = new WarningContentDto();
            warningContentDto.setContent(warningContent.getContent());
            warningContentDto.setWaringAddress(warningContent.getWaringAddress());
            warningContentDto.setWaringTime(warningContent.getWaringTime());
            warningContentDto.setWarningType(warningContent.getWarningType());
            warningContentDtoList.add(warningContentDto);
        }
        sortByWaringTime(warningContentDtoList);
        warningDetailDto.setWarningContentDtoList(warningContentDtoList);
        WorkOrder workOrder = earlyWarning.getWorkOrder();
        if (MonkeyUtils.isNotEmpty(workOrder)) {
            User user = workOrder.getUser();
            List<WorkOrderServiceRecord> serviceList = workOrderServiceRecordRepository.getServiceList(workOrder);
            for (WorkOrderServiceRecord workOrderServiceRecord : serviceList) {
                if (WorkOrderServiceType.Finish.equals(workOrderServiceRecord.getWorkOrderServiceType())) {
                    warningDetailDto.setFinishTime(workOrderServiceRecord.getCreateTime());
                    warningDetailDto.setFinishContent(user.getName() + "完成了服务");
                }
            }
        }
        return warningDetailDto;
    }

    private void sortByWaringTime(List<WarningContentDto> warningContentDtoList) {
        Collections.sort(warningContentDtoList, new Comparator<WarningContentDto>() {
            public int compare(WarningContentDto o1, WarningContentDto o2) {
                Date createTime1 = o1.getWaringTime();
                Date createTime2 = o2.getWaringTime();
                if (createTime1.getTime() > createTime2.getTime()) {
                    return -1;
                }
                return 1;
            }
        });
    }

    @Override
    public List<AllWaringListDto> getWarningAllList() {
        List<EarlyWarning> earlyWarningList = earlyWarningRepository.getWarningAllList();
        return buildAllWaringListDto(earlyWarningList);
    }

    @Override
    public void updatePlayStatus(Long waringId) {
        EarlyWarning earlyWarning = earlyWarningRepository.findOne(waringId);
        earlyWarning.setPlay(true);
        earlyWarningRepository.save(earlyWarning);
    }

    @Override
    public SystemSetup getLocationSet() {
        User user = SecurityUtils.getCurrentUser();
        if (MonkeyUtils.isEmpty(user)) {
            throw new MonkeyException("没有获取登录信息");
        }
        return systemSetupRepository.findByUser(user);
    }

    @Override
    public void updateLocationSet(Long id) {
        if (MonkeyUtils.isNotEmpty(id)) {
            SystemSetup systemSetup = systemSetupRepository.findOne(id);
            if (MonkeyUtils.isNotEmpty(systemSetup)) {
                if (systemSetup.getPositioningSwitch()) {
                    systemSetup.setPositioningSwitch(false);
                } else {
                    systemSetup.setPositioningSwitch(true);
                }
                systemSetupRepository.save(systemSetup);
            }
        }
    }

    @Override
    public void updateTheme(Long id, Long themeId) {
        if (MonkeyUtils.isNotEmpty(id)) {
            SystemSetup systemSetup = systemSetupRepository.findOne(id);
            if (MonkeyUtils.isNotEmpty(systemSetup)) {
                Dictionary dictionary = dictionaryRepository.findOne(themeId);
                if (MonkeyUtils.isEmpty(dictionary)) {
                    throw new MonkeyException("主题不存在");
                }
                systemSetup.setTheme(dictionary);
                systemSetupRepository.save(systemSetup);
            }
        }
    }

    private List<AllWaringListDto> buildAllWaringListDto(List<EarlyWarning> earlyWarningList) {
        List<AllWaringListDto> waringListDtos = new ArrayList<>();
        if (MonkeyUtils.isNotEmpty(earlyWarningList)) {
            for (EarlyWarning earlyWarning : earlyWarningList) {
                AllWaringListDto allWaringListDto = new AllWaringListDto();
                allWaringListDto.setName(earlyWarning.getName());
                allWaringListDto.setStatus(earlyWarning.getStatus());
                allWaringListDto.setBeeper(earlyWarning.getBeeper());
                allWaringListDto.setLongitude(earlyWarning.getLongitude());
                allWaringListDto.setLatitude(earlyWarning.getLatitude());
                allWaringListDto.setWaringId(earlyWarning.getId());
                List<WarningContent> warningContents = earlyWarning.getWarningContents();
                if (MonkeyUtils.isNotEmpty(warningContents)) {
                    for (WarningContent warningContent : warningContents) {
                        List<String> stringList = new ArrayList<>();
                        stringList.add(warningContent.getContent());
                        allWaringListDto.setStringList(stringList);
                    }
                }
                waringListDtos.add(allWaringListDto);
            }
        }
        return waringListDtos;
    }


    private List<DangerWarningListDto> buildDangerWarningListDto(List<EarlyWarning> warningList) {
        List<DangerWarningListDto> warningListDtoList = new ArrayList<>();
        for (EarlyWarning earlyWarning : warningList) {
            DangerWarningListDto dangerWarningListDto = new DangerWarningListDto();
            dangerWarningListDto.setBeeper(earlyWarning.getBeeper());
            dangerWarningListDto.setWaringId(earlyWarning.getId());
            dangerWarningListDto.setAge(earlyWarning.getAge());
            dangerWarningListDto.setName(earlyWarning.getName());
            dangerWarningListDto.setAvatar(earlyWarning.getAvatar());
            dangerWarningListDto.setPlay(earlyWarning.getPlay());
            dangerWarningListDto.setSex(earlyWarning.getSex().getLabel());
            dangerWarningListDto.setLongitude(earlyWarning.getLongitude());
            dangerWarningListDto.setLatitude(earlyWarning.getLatitude());
            dangerWarningListDto.setStatus(earlyWarning.getStatus());
            List<WarningContent> warningContentList = earlyWarning.getWarningContents();
            List<String> stringList = new ArrayList<>();
            for (WarningContent warningContent : warningContentList) {
                stringList.add(warningContent.getContent());
                dangerWarningListDto.setWaringDate(warningContent.getWaringTime());
            }
            dangerWarningListDto.setWaringData(stringList);
            buildEarlyWaringDto(earlyWarning, dangerWarningListDto);
            warningListDtoList.add(dangerWarningListDto);
        }
        return warningListDtoList;
    }

    private void buildEarlyWaringDto(EarlyWarning earlyWarning, DangerWarningListDto dangerWarningListDto) {

        if (!earlyWarning.getPlay()) {
            UploadFileInfo uploadFileInfo = null;
            List<WarningContent> warningContents = earlyWarning.getWarningContents();
            for (WarningContent warningContent : warningContents) {
                if (WarningType.Sos.equals(warningContent.getWarningType())) {
                    uploadFileInfo = speechSynthesisService.SendSpeech(earlyWarning.getName() + "发出SOS呼救");
                } else if (WarningType.Phone_Help.equals(warningContent.getWarningType())) {
                    uploadFileInfo = speechSynthesisService.SendSpeech(earlyWarning.getName() + warningContent.getContent());
                } else if (WarningType.Heart_Rate.equals(warningContent.getWarningType())) {
                    uploadFileInfo = speechSynthesisService.SendSpeech(earlyWarning.getName() + "心率预警");
                } else if (WarningType.Blood_Pressure.equals(warningContent.getWarningType())) {
                    uploadFileInfo = speechSynthesisService.SendSpeech(earlyWarning.getName() + "血压预警");
                } else if (WarningType.Enclosure.equals(warningContent.getWarningType())) {
                    uploadFileInfo = speechSynthesisService.SendSpeech(earlyWarning.getName() + "电子围栏预警");
                } else {
                    uploadFileInfo = speechSynthesisService.SendSpeech(earlyWarning.getName() + "发起呼叫");
                }
            }
            String accessURL = this.fileService.getAccessURL(uploadFileInfo.getPath());
            dangerWarningListDto.setSpeechUrl(accessURL);
        }
    }

    private List<WaringListDto> initWaringListDto(List<EarlyWarning> earlyWarningList) {
        List<WaringListDto> waringListDtoList = new ArrayList<>();
        for (EarlyWarning earlyWarning : earlyWarningList) {
            WaringListDto waringListDto = new WaringListDto();
            waringListDto.setWaringId(earlyWarning.getId());
            waringListDto.setNumber(earlyWarning.getNumber());
            waringListDto.setServiceType(earlyWarning.getServiceType().getLabel());
            String phone = earlyWarning.getPhone();
            if (MonkeyUtils.isEmpty(phone)) {
                phone = "";
            }
            waringListDto.setLaunch(earlyWarning.getName() + phone);
            waringListDtoList.add(waringListDto);
        }
        return waringListDtoList;
    }

    private <M> List<M> limitList(int pageIndex, int pageSize, int total, List<M> data) {
        // 根据 条件获取到 分页的结构和数据
        List<M> list;
        if (total < pageSize) {
            list = data.subList(pageIndex, total);
        } else {
            int toSize = pageIndex + pageSize;
            if (toSize > total) {
                toSize = pageIndex + total % pageSize;
            }
            list = data.subList(pageIndex, toSize);
        }
        return list;
    }

    private EarlyWarning initEarlyWarning(MonkeyDto monkeyDto) {
        String identifier = monkeyDto.getString("identifier");
        Searchable searchable = Searchable.newSearchable();
        searchable.addSearchFilter("serviceType", SearchOperator.eq, WarningServiceType.None);
        searchable.addSearchFilter("identifier", SearchOperator.eq, identifier);
        List<EarlyWarning> earlyWarningList = earlyWarningRepository.findAll(searchable).getContent();
        if (MonkeyUtils.isNotEmpty(earlyWarningList)) {
            if (earlyWarningList.size() > 1) {
                throw new MonkeyException("数据库数据异常");
            }
            for (EarlyWarning earlyWarning : earlyWarningList) {
                buildEarlyWarning(earlyWarning, monkeyDto);
                return earlyWarning;
            }
        }
        EarlyWarning earlyWarning = new EarlyWarning();
        buildEarlyWarning(earlyWarning, monkeyDto);
        Long orgId = monkeyDto.getLong("orgId");
        earlyWarning.setCompanyId(orgId);
        earlyWarning.setNumber(numberGenerator.generateWaringNumber(orgId));
        return earlyWarning;
    }

    private void saveWarningContent(EarlyWarning earlyWarning, MonkeyDto monkeyDto) {
        WarningContent warningContent = new WarningContent();
        String waringType = monkeyDto.getString("waringType");
        warningContent.setWarningType(WarningType.valueOf(waringType));
        warningContent.setContent(monkeyDto.getString("content"));
        warningContent.setEarlyWarning(earlyWarning);
        warningContent.setWaringTime(new Date());
        warningContent.setWaringAddress(monkeyDto.getString("waringAddress"));
        Long orgId = monkeyDto.getLong("orgId");
        warningContent.setCompanyId(orgId);
        warningContentRepository.save(warningContent);
    }

    private void buildEarlyWarning(EarlyWarning earlyWarning, MonkeyDto monkeyDto) {
        String longitude = monkeyDto.getString("longitude");
        String latitude = monkeyDto.getString("latitude");
        earlyWarning.setName(monkeyDto.getString("name"));
        if (MonkeyUtils.isEmpty(longitude)|| "0.0".equals(longitude)) {
            longitude = "105.982564";
        }
        if (MonkeyUtils.isEmpty(latitude)||"0.0".equals(latitude)) {
            latitude = "28.531505";
        }
        earlyWarning.setLongitude(longitude);
        earlyWarning.setLatitude(latitude);
        String waringType = monkeyDto.getString("waringType");
        if (WarningType.Calling_Device.equals(WarningType.valueOf(waringType))) {
            Device device = deviceRepository.findByNumber(monkeyDto.getString("identifier"));
            if (MonkeyUtils.isNotEmpty(device)) {
                earlyWarning.setName(device.getName());
                earlyWarning.setLongitude(device.getLongitude());
                earlyWarning.setLatitude(device.getLatitude());
            }
            earlyWarning.setBeeper(true);
        }
        earlyWarning.setAvatar(monkeyDto.getString("avatar"));
        earlyWarning.setAge(monkeyDto.getInteger("age"));
        earlyWarning.setIdentifier(monkeyDto.getString("identifier"));
        earlyWarning.setPhone(monkeyDto.getString("phone"));
        earlyWarning.setServiceType(WarningServiceType.None);
        String sex = monkeyDto.getString("sex");
        if (MonkeyUtils.isNotEmpty(sex)) {
            earlyWarning.setSex(Sex.valueOf(sex));
        }
        String status = monkeyDto.getString("status");
        if (HealthStatus.DANGER.equals(HealthStatus.valueOf(status))) {
            earlyWarning.setPlay(false);
            earlyWarning.setCreateTime(new Date());
        } else {
            earlyWarning.setPlay(true);
        }
        if (MonkeyUtils.isNotEmpty(earlyWarning.getStatus())) {
            if (HealthStatus.DANGER.equals(earlyWarning.getStatus())) {

            } else {
                if (MonkeyUtils.isNotEmpty(status)) {
                    earlyWarning.setStatus(HealthStatus.valueOf(status));
                }
            }
        } else {
            if (MonkeyUtils.isNotEmpty(status)) {
                earlyWarning.setStatus(HealthStatus.valueOf(status));
            }
        }
    }
}
